﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CAGFIP.Jogo;
using CAGFIP.Utils;
using System.Drawing;

namespace CAGFIP.GUI
{
    public class TelaPergunta : Panel
    {
        #region Fields

        delegate void ResetProgressBarCallback();

        private int qtdeRemAltRodada;

        #endregion

        #region Windows Forms Fields

        private List<RadioButton> alternativas;

        private TextBox pergunta;

        private Button pularPergunta;
        private Button removerAlternativa;
        private Button chutar;
        private Button responder;
        private Button desistir;

        private ToolTip chutarToolTip;
        private ToolTip pularToolTip;
        private ToolTip remAltToolTip;

        private Label pulosRestantes;
        private Label remocoesRestantes;
        private Label chutesRestantes;
        private Label pontuacaoLabel;

        private ProgressBar barraTempo;

        private System.Windows.Forms.Timer timer;
        private System.Timers.Timer countdownTimer;

        #endregion

        #region Properties

        private System.Windows.Forms.Timer Timer
        {
            get
            {
                if (this.timer == null)
                {
                    var timer = new System.Windows.Forms.Timer();
                    timer.Interval = 1000;
                    timer.Tick += new EventHandler(timer_Tick);

                    this.timer = timer;
                }
                return this.timer;
            }
        }

        private System.Timers.Timer CountdownTimer
        {
            get
            {
                if (this.countdownTimer == null)
                {
                    var timer = new System.Timers.Timer();
                    timer.AutoReset = false;
                    timer.Elapsed += new System.Timers.ElapsedEventHandler(countdownTimer_Elapsed);

                    this.countdownTimer = timer;
                }
                return this.countdownTimer;
            }
        }

        #endregion

        #region Constructors
        
        public TelaPergunta()
        {
            this.qtdeRemAltRodada = 0;
            this.Dock = DockStyle.Fill;
            this.Location = new System.Drawing.Point(0, 0);
            initComponents();
        }
        private void initComponents()
        {
            #region Radio Config

            alternativas = new List<RadioButton>(Constants.QtdeAlternativas);

            //TODO: reorganizar alternativas

            var alternativa1 = new RadioButton();
            alternativa1.AutoSize = true;
            alternativa1.Location = new System.Drawing.Point(38, 223);
            alternativa1.TabIndex = 0;
            alternativa1.TabStop = true;
            alternativa1.Text = "alt1";
            alternativa1.UseVisualStyleBackColor = true;

            var alternativa2 = new RadioButton();
            alternativa2.AutoSize = true;
            alternativa2.Location = new System.Drawing.Point(38, 247);
            alternativa2.TabIndex = 1;
            alternativa2.TabStop = true;
            alternativa2.Text = "alt2";
            alternativa2.UseVisualStyleBackColor = true;

            var alternativa3 = new RadioButton();
            alternativa3.AutoSize = true;
            alternativa3.Location = new System.Drawing.Point(38, 271);
            alternativa3.TabIndex = 2;
            alternativa3.TabStop = true;
            alternativa3.Text = "alt3";
            alternativa3.UseVisualStyleBackColor = true;

            var alternativa4 = new RadioButton();
            alternativa4.AutoSize = true;
            alternativa4.Location = new System.Drawing.Point(38, 295);
            alternativa4.TabIndex = 3;
            alternativa4.TabStop = true;
            alternativa4.Text = "alt4";
            alternativa4.UseVisualStyleBackColor = true;

            var alternativa5 = new RadioButton();
            alternativa5.AutoSize = true;
            alternativa5.Location = new System.Drawing.Point(38, 319);
            alternativa5.TabIndex = 4;
            alternativa5.TabStop = true;
            alternativa5.Text = "alt5";
            alternativa5.UseVisualStyleBackColor = true;

            alternativas.Add(alternativa1);
            alternativas.Add(alternativa2);
            alternativas.Add(alternativa3);
            alternativas.Add(alternativa4);
            alternativas.Add(alternativa5);

            #endregion

            #region TextBox Pergunta Config

            pergunta = new TextBox();
            pergunta.Multiline = true;
            pergunta.Location = new System.Drawing.Point(38, 85);
            pergunta.Size = new System.Drawing.Size(380, 132);
            pergunta.ReadOnly = true;
            pergunta.BackColor = System.Drawing.Color.White;

            #endregion

            #region Button Config

            pularPergunta = new Button();
            pularPergunta.BackgroundImageLayout = ImageLayout.None;
            pularPergunta.FlatAppearance.BorderSize = 0;
            pularPergunta.FlatStyle = FlatStyle.Flat;
            pularPergunta.Image = global::CAGFIP.GUI.Properties.Resources.pulo;
            pularPergunta.Location = new System.Drawing.Point(592, 85);
            pularPergunta.Size = new System.Drawing.Size(65, 74);
            pularPergunta.TabIndex = 5;
            pularPergunta.UseVisualStyleBackColor = true;
            pularPergunta.Click += new EventHandler(pularPergunta_Click);

            removerAlternativa = new Button();
            removerAlternativa.BackgroundImageLayout = ImageLayout.None;
            removerAlternativa.FlatAppearance.BorderSize = 0;
            removerAlternativa.FlatStyle = FlatStyle.Flat;
            removerAlternativa.Image = global::CAGFIP.GUI.Properties.Resources.remover;
            removerAlternativa.Location = new System.Drawing.Point(582, 207);
            removerAlternativa.Size = new System.Drawing.Size(75, 71);
            removerAlternativa.TabIndex = 6;
            removerAlternativa.UseVisualStyleBackColor = true;
            removerAlternativa.Click += new EventHandler(removerAlternativa_Click);

            chutar = new Button();
            chutar.BackgroundImageLayout = ImageLayout.None;
            chutar.FlatAppearance.BorderSize = 0;
            chutar.FlatStyle = FlatStyle.Flat;
            chutar.Image = global::CAGFIP.GUI.Properties.Resources.chute;
            chutar.Location = new System.Drawing.Point(582, 319);
            chutar.Size = new System.Drawing.Size(75, 56);
            chutar.TabIndex = 7;
            chutar.UseVisualStyleBackColor = true;

            chutar.Click += new EventHandler(chutar_Click);

            responder = new Button();
            responder.Location = new System.Drawing.Point(38, 527);
            responder.Size = new System.Drawing.Size(75, 23);
            responder.TabIndex = 8;
            responder.Text = "Responder";
            responder.UseVisualStyleBackColor = true;
            responder.Click += new EventHandler(responder_Click);

            desistir = new Button();
            desistir.Location = new System.Drawing.Point(592, 527);
            desistir.Size = new System.Drawing.Size(75, 23);
            desistir.TabIndex = 9;
            desistir.Text = "Desistir";
            desistir.UseVisualStyleBackColor = true;
            desistir.Click += new EventHandler(desistir_Click);

            #endregion

            #region Tooltip Config

            chutarToolTip = new ToolTip();
            chutarToolTip.SetToolTip(chutar, "Chutar alternativa selecionada");

            remAltToolTip = new ToolTip();
            remAltToolTip.SetToolTip(removerAlternativa, "Remover alternativa aleatoriamente");

            pularToolTip = new ToolTip();
            pularToolTip.SetToolTip(pularPergunta, "Pular pergunta atual");

            #endregion

            #region Label Config

            pulosRestantes = new Label();
            pulosRestantes.AutoSize = true;
            pulosRestantes.Location = new System.Drawing.Point(613, 162);

            remocoesRestantes = new Label();
            remocoesRestantes.AutoSize = true;
            remocoesRestantes.Location = new System.Drawing.Point(613, 281);

            chutesRestantes = new Label();
            chutesRestantes.AutoSize = true;
            chutesRestantes.Location = new System.Drawing.Point(613, 378);

            pontuacaoLabel = new Label();
            pontuacaoLabel.AutoSize = true;
            pontuacaoLabel.Location = new System.Drawing.Point(315, 527);

            #endregion

            #region ProgressBar Tempo Config

            barraTempo = new ProgressBar();
            barraTempo.Dock = DockStyle.Right;
            barraTempo.Location = new System.Drawing.Point(755, 0);
            barraTempo.RightToLeft = RightToLeft.No;
            barraTempo.Size = new System.Drawing.Size(29, 562);
            barraTempo.Style = ProgressBarStyle.Continuous;

            #endregion

            #region Controls

            this.Controls.Add(pergunta);

            for (int i = 0; i < Constants.QtdeAlternativas; i++)
            {
                this.Controls.Add(alternativas[i]);
            }
            this.Controls.Add(pularPergunta);
            this.Controls.Add(removerAlternativa);
            this.Controls.Add(chutar);
            this.Controls.Add(pulosRestantes);
            this.Controls.Add(remocoesRestantes);
            this.Controls.Add(chutesRestantes);
            this.Controls.Add(responder);
            this.Controls.Add(desistir);
            this.Controls.Add(barraTempo);
            this.Controls.Add(pontuacaoLabel);

            #endregion
        }

        #endregion

        #region GUIUpdates

        internal void chuteUpdateHandler(int qtdeRestante)
        {
            this.chutesRestantes.Text = String.Format("({0})", qtdeRestante);
            if (qtdeRestante == 0)
                this.chutar.Enabled = false;
        }

        internal void puloUpdateHandler(int qtdeRestante)
        {
            this.pulosRestantes.Text = String.Format("({0})", qtdeRestante);
            if (qtdeRestante == 0)
                this.pularPergunta.Enabled = false;
        }

        internal void remAltUpdateHandler(int qtdeRestante)
        {
            this.remocoesRestantes.Text = String.Format("({0})", qtdeRestante);
            if (++qtdeRemAltRodada == Constants.QtdeAlternativasIncorretas || qtdeRestante == 0)
                this.removerAlternativa.Enabled = false;
        }

        internal void pontuacaoUpdateHandler(float pontuacao)
        {
            //TODO
            if (this.InvokeRequired)
                this.Invoke(new Action<float>(SetPontuacao), new object[] { pontuacao } );
            else
                SetPontuacao(pontuacao);
        }

        private void SetPontuacao(float pontuacao)
        {
            pontuacaoLabel.Text = "Pontuação : " + pontuacao.ToString();
        }

        #endregion

        public void InicializarRodada(string enunciado, AlternativaCollection alternativas, int tempo)
        {

            //pergunta
            pergunta.Text = enunciado;

            //alternativas
            for (int i = 0; i < Constants.QtdeAlternativas; i++)
            {
                this.alternativas[i].Text = alternativas[i];
                this.alternativas[i].Visible = true;
            }

            this.alternativas[0].Checked = true;

            //remocoesAlternativa
            remocoesRestantes.Visible = true;

            if (qtdeRemAltRodada == Constants.QtdeAlternativasIncorretas)
                this.removerAlternativa.Enabled = true;

            this.qtdeRemAltRodada = 0;

            //timers e progressbar
            barraTempo.Maximum = tempo;

            Timer.Start();

            CountdownTimer.Interval = tempo * 1000;
            CountdownTimer.Start();
        }

        void timer_Tick(object sender, EventArgs e)
        {
            barraTempo.Increment(1);
        }

        void countdownTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            ControladorGUI.Instance.OnTempoExpirado();
        }

        void desistir_Click(object sender, EventArgs e)
        {
            ControladorGUI.Instance.OnDesistenciaRequest();
        }

        void responder_Click(object sender, EventArgs e)
        {
            int idx = alternativas.FindIndex(delegate(RadioButton predicate)
            {
                return predicate.Checked;
            });

            ControladorGUI.Instance.OnAlternativaSelecionada(idx);
        }

        void chutar_Click(object sender, EventArgs e)
        {
            int idx = alternativas.FindIndex(delegate(RadioButton predicate)
            {
                return predicate.Checked;
            });

            ControladorGUI.Instance.OnChute(idx);
        }

        void removerAlternativa_Click(object sender, EventArgs e)
        {
            ControladorGUI.Instance.OnRemocaoAlternativa();
        }

        void pularPergunta_Click(object sender, EventArgs e)
        {
            ControladorGUI.Instance.OnPulo();
        }

        private void ResetProgressBar()
        {
            barraTempo.Value = 0;
        }

        internal void PararTimers()
        {
            Timer.Stop();
            CountdownTimer.Stop();
            if (barraTempo.InvokeRequired)
                barraTempo.Invoke(new ResetProgressBarCallback(ResetProgressBar));
            else
                ResetProgressBar();
        }
        internal void ReiniciarTimers()
        {
            CountdownTimer.Stop();
            CountdownTimer.Start();
            if (barraTempo.InvokeRequired)
                barraTempo.Invoke(new ResetProgressBarCallback(ResetProgressBar));
            else
                ResetProgressBar();
        }

        internal void DesabilitarAlternativa(int idx, int selectionIdx)
        {
            alternativas[idx].Visible = false;
            alternativas[selectionIdx].Checked = true;
        }

        internal void DoCleanup()
        {
            PararTimers();

            //botoes p/ prox jogo
            if (this.InvokeRequired)
                this.Invoke(new Action(ResetButtons));
            else
                ResetButtons();
        }
        internal void ResetButtons()
        {
            this.pularPergunta.Enabled = this.chutar.Enabled = this.removerAlternativa.Enabled = true;
        }
    }
}
